﻿using System;
using System.Text.RegularExpressions;

using DDDSample.Common.Validate;

namespace DDDSample.Domain.Model.Locations
{
	/// <summary>
	/// United nations location code.
	/// <para />
	/// http://www.unece.org/cefact/locode/
	/// http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
	/// </summary>
	public sealed class UnLocode : ValueObject<UnLocode>
	{
		private string unLocode;

		// Country code is exactly two letters.
		// Location code is usually three letters, but may contain the numbers 2-9 as well
		private static Regex VALID_PATTERN = new Regex("^[a-zA-Z]{2}[a-zA-Z2-9]{3}$");

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="countryAndLocation">Location string.</param>
		public UnLocode(string countryAndLocation)
		{
			Validate.NotNull(countryAndLocation, "Country and location may not be null");
			Validate.IsTrue(VALID_PATTERN.IsMatch(countryAndLocation), countryAndLocation + " is not a valid UN/LOCODE (does not match pattern)");

			this.unLocode = countryAndLocation.ToUpper();
		}

		/// <summary>
		/// country code and location code concatenated, always upper case.
		/// </summary>
		public string IdString
		{
			get { return this.unLocode; }
		}

		public override bool Equals(object obj)
		{
			if (this == obj) return true;
			if (obj == null || GetType() != obj.GetType()) return false;

			UnLocode other = (UnLocode)obj;

			return SameValueAs(other);
		}

		public override bool SameValueAs(UnLocode other)
		{
			return other != null && this.unLocode.Equals(other.unLocode);
		}

		public override int GetHashCode()
		{
			return this.unLocode.GetHashCode();
		}

		public override string ToString()
		{
			return this.IdString;
		}

		private UnLocode()
		{
			// Needed by Hibernate
		}
	}
}
